<script setup>
import * as ort from 'onnxruntime-web'
import {predict, preprocess,RecordPreprocess} from "@/utils/runtime"
import {computed, ref,onBeforeMount,getCurrentInstance} from 'vue';
import * as echarts from 'echarts';
import request from "@/utils/request";
import axios from 'axios'

/**
 * wasm工件，onnxruntime-web里面有
 * @type {{"ort-wasm.wasm": string, "ort-wasm-simd.wasm": string, "ort-wasm-threaded.wasm": string, "ort-wasm-simd-threaded.wasm": string}}
 */
ort.env.wasm.wasmPaths={
  'ort-wasm.wasm': 'ort-wasm.wasm',
  'ort-wasm-threaded.wasm':
      'ort-wasm-threaded.wasm',
  'ort-wasm-simd.wasm':
      'ort-wasm-simd.wasm',
  'ort-wasm-simd-threaded.wasm':
      'ort-wasm-simd-threaded.wasm'
}
const executionProvider = ref('wasm')//内置变量
const modelUrl = ref('')
const model = ref(null)
const selectFilename=ref('')
const classIndices = ref(null)
const model_url ='file/MobileNetV2.onnx'//推理模型路径
//读取映射文件
async function  readClassFile() {
  const classes_url='file/chenpi_5.json'//
  const classes_text = await fetch(classes_url).then((response) => response.text())
  classIndices.value = JSON.parse(classes_text)
  console.log(classIndices.value)
  return classIndices.value
}

//读取模型
async function readModelFile(){

  model.value = await ort.InferenceSession.create(model_url, {//创建新的推理会话并从 ONNX 模型文件异步加载模型。
    executionProviders: [executionProvider.value]
  })
  console.log(model.value)
  return model.value
}


const inputImageUrl = ref('')

const isLoadingModel = ref(false)
const isLoadingPredict = ref(false)
const canPredict = computed(async () => {
  model.value = await readModelFile();
  return model.value && classIndices.value
})

const seriesData = ref([])
const seriesLabels = ref([])
const timeCost = ref(0)


const canvas = ref(null)

const  src =ref('')
async function imageFileChangeHandler (event){
  const image_file = (event.target).files?.[0] ?? null
  selectFilename.value=event.target.files[0].name
  const currentDate = new Date();
  if (image_file) {
    seriesData.value = []
    seriesLabels.value = []
    const inputImageBlob = new Blob([image_file])
    inputImageUrl.value = URL.createObjectURL(inputImageBlob)
    console.log(inputImageUrl.value)
    isLoadingPredict.value = true
    model.value=await readModelFile();//读取模型
    classIndices.value=await readClassFile();//读取映射文件
    if (model.value && classIndices.value) {
      const inputTensor = await preprocess(inputImageUrl.value)//处理图片并返回张量
      console.log(inputTensor)
      const res = await predict(model.value, inputTensor, classIndices.value)
      if (res) {
        timeCost.value = res.timeCost
        seriesData.value = res.data
        seriesLabels.value = res.labels
        drawChart();
        console.log(timeCost.value,seriesData.value, seriesLabels.value)
        console.log(seriesLabels.value.at(0))
        console.log(timeCost.value)
        console.log(seriesData.value)
        console.log(seriesLabels.value)
        console.log(inputImageUrl)
        console.log(currentDate)


        const formData = new FormData();
        formData.append('file', image_file);
        console.log(formData)

        axios.post('http://localhost:9090/files/upload', formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        })
            .then(response => {
              console.log('Upload success:', response.data.data);
              src.value=response.data.data;
              console.log(src)
              const fileName = src.value.substring(src.value.lastIndexOf('/') + 1);
              console.log(fileName)
              console.log(src)
              const postData={
                name:fileName,
                res:seriesLabels.value.at(0),
                date:currentDate,
              }
              request.post('/record/add',postData)
                  .then(res => {
                    console.log('done')
                  }).catch(error=>{
                console.error(error)
              })
            })
            .catch(error => {
              console.error('Upload error:', error);
            });
        await reload();
      }
    }


    isLoadingPredict.value = false
  }
}

async function RecordImageFileChangeHandler (src){
  console.log(src)
  console.log("done")
      console.log("done")

      const inputTensor = await RecordPreprocess(src)//处理图片并返回张量

      console.log(inputTensor);
  console.log(model.value)
  console.log(classIndices.value)

  model.value=await readModelFile();//读取模型
  classIndices.value=await readClassFile();//读取映射文件
      const res = await predict(model.value, inputTensor, classIndices.value)
  console.log(res);
      if (res) {
        console.log("done")
        timeCost.value = res.timeCost
        seriesData.value = res.data
        seriesLabels.value = res.labels
        drawChart();
        console.log(timeCost.value,seriesData.value, seriesLabels.value)
        console.log(timeCost.value)
        console.log(seriesData.value)
        console.log(seriesLabels.value)
        console.log(inputImageUrl)
        inputImageUrl.value='http://localhost:9090/files/'+src
      }

    isLoadingPredict.value = false
  selectFilename.value=null

}

// predict
const imagePredictHandler = async () => {
  const imageUploader = document.getElementById('imageUploader')
  if (imageUploader) {
    imageUploader.click()
  }
}
//转换结果为百分比
function convertArrayToPercentage(inputArray) {
  // 计算数组中所有元素的总和
  const sum = inputArray.reduce((acc, val) => acc + val, 0);

  // 将每个元素转换为百分比形式，并存储在新数组中,保留两位小数
  const percentageArray = inputArray.map(val => ((val / sum) * 100).toFixed(2));

  return percentageArray;
}

 function drawChart() {
  // 基于准备好的dom，初始化echarts实例
   let elementById = document.getElementById("main");
  const myChart = echarts.init(elementById);
  // 指定图表的配置项和数据
  let option = {
    title: {
      text: "Top5 类别预测结果",
    },
    tooltip: {

    },

    legend: {
    },
    toolbox: {
      show: true,
      orient: "vertical",
      left: "right",
      top: "top",
      feature: {
        saveAsImage: { show: true },  // 保存图表
      },
    },
    xAxis: {
      data: seriesLabels.value
    },
    yAxis: {
      type: 'value',
      axisLabel: {
        formatter: '{value}%', // Y 轴标签格式化为百分比
      },
    },
    series: [
      {
        type: "bar",
        data: convertArrayToPercentage(seriesData.value),
        barWidth: '50%',
        label: {
          show: true,
          position: 'top',
          formatter:'{c}%'
        },
        itemStyle: {
          barBorderRadius: 10,
          borderWidth: 1,
          borderType: 'solid',
          shadowColor: '#5470c6',
          shadowBlur: 3
        }

      },

    ],

  };
  // 使用刚指定的配置项和数据显示图表。
  myChart.setOption(option);
}

const currentPage= ref(1);
const pageSize=ref(5);
const recordData=ref('')
const total=ref(0)
function handleSizeChange(size) {
  pageSize.value = size;//每页下拉显示数据
}
function handleCurrentChange(currentPage){
  reload(currentPage);
}
let user = JSON.parse(localStorage.getItem("xm-user") || '{}')
const token=user.token;

console.log(token)

  onBeforeMount(async =>{
    reload(1);

})


async function reload(currentPage){
  axios.get('http://localhost:9090/record/selectPage', {
    params: {
      pageSize:pageSize.value,
      pageNum:currentPage,
    },
    headers: { // 设置请求头
      token:token
    }
  }).then(
      success=>{
        console.log('请求成功！')
        console.log(success)
        recordData.value=success.data.data.list
        /*const myArray = [];
        for (let i = 0; i < recordData.value.length; i++) {
          myArray.push(recordData.value[i].name.substring(recordData.value[i].name.lastIndexOf('-') + 1));
        }
        console.log(myArray)*/
        total.value=success.data.data.total
        console.log(recordData)
      },
      error=>{
        console.log('请求失败！')
        console.log(error.message)
      }
  )
}

const ids =ref([])
function delBatch() {   // 批量删除
  console.log("done")
  if (!ids.value.length) {
   alert('请选择数据');
    console.log("done")
    return
  }
    request.delete('/record/delete/batch', {data: ids.value}).then(res => {
      console.log("done")
      if (res.code === '200') {   // 表示操作成功
       alert('操作成功');
        reload()
      } else {
        alert('操作失败');  // 弹出错误的信息
      }
    })
}

function del(id) {
  request.delete('/record/delete/' + id).then(res => {
    console.log("done")
    if (res.code === '200') {   // 表示操作成功
      alert('操作成功');
      reload()
    } else {
      alert('操作失败');  // 弹出错误的信息
    }
  })
}

 function handleSelectionChange(rows) {   // 当前选中的所有的行数据
  ids.value = rows.map(v => v.id)
   console.log(ids)
}

</script>

<template>
  <div>
    <div style="display: flex">
      <el-card class="box-card">
        <div slot="header" class="clearfix" style="text-align: center">
          <span style="font-family: 'Microsoft YaHei',微软雅黑;font-weight: bold;font-size: large;">上传图像</span>
        </div>
        <input
            hidden="hidden"
            type="file"
            accept="image/*"
            name="image"
            id="imageUploader"
            @change="imageFileChangeHandler"
        />
        <el-button
          type="primary"
          id="imagePredict"
          @click="imagePredictHandler"
          size="medium"
          plain
          style="margin-left: 100px;margin-top: 40px;"
        >
          上传图像推理<i class="el-icon-upload el-icon--right"></i>
        </el-button>

        <span v-if="selectFilename" style="margin-left: 30px;display: inline-block" >{{selectFilename}}</span>
      </el-card>

      <el-card style="margin-left: 10px;width: 1000px; height: 250px;margin-top: 10px;display: flex" >
          <div style="display: flex;margin-left: 75px;" >
              <div id="main" style="width:500px; height: 245px"></div>
              <div class="block" style="margin-left: 50px;display: flex" >
                  <img v-if="inputImageUrl" :src="inputImageUrl" width="200px" height="200px" />
              </div>
          </div>

      </el-card>

    </div>




<div>
  <el-card class="record" style="margin-top: 10px;width: 1410px">
    <div slot="header" class="clearfix">
      <span>鉴定记录</span>
      <el-button style="margin-left: 20px" type="danger" plain @click="delBatch">批量删除</el-button>
    </div>
    <div class="table">
      <el-table :data="recordData" strip @selection-change="handleSelectionChange" style="max-height: 400px;min-height: 250px;">
        <el-table-column type="selection" width="55" align="center"></el-table-column>
        <el-table-column prop="id" label="序号" width="70" align="center" sortable></el-table-column>
        <el-table-column prop="name" label="名字" ></el-table-column>
        <el-table-column prop="res" label="结果" align="center"></el-table-column>
        <el-table-column prop="date" label="日期" align="center"></el-table-column>
        <el-table-column label="操作" align="center" width="180">
          <template v-slot="scope">
            <el-button size="mini" type="primary" plain @click="() => RecordImageFileChangeHandler(scope.row.name) ">查看</el-button>
            <el-button size="mini" type="danger" plain @click="() => del(scope.row.id) ">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination">
        <el-pagination
            background
            @current-change="handleCurrentChange"
            :current-page="currentPage"
            :page-sizes="[5, 10, 20]"
            :page-size="pageSize"
            layout="total, prev, pager, next"
            :total="total">
        </el-pagination>
      </div>
    </div>
  </el-card>
</div>


</div>
</template>
<style >

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}

.clearfix:after {
  clear: both
}
.record{
  margin-top: 0px;
}
.box-card {
  margin-left: 0px;
  margin-top: 10px;
  position: relative;
  width: 400px;
  height: 250px;
}

</style>
